@model WalkingTec.Mvvm.Core.BaseVM
<wt:fieldset field-set-style="Simple" title="TopBasePoco">
    <p>TopBasePoco是框架所有模型的基类，它只定义了一个Guid的主键，所有其他模型都必须直接或间接继承TopBasePoco，否则框架的其他自动化操作无法执行</p>
    <wt:quote>
        <p>从2.3.5开始，框架支持自定义主键类别，除了Guid之外，还支持自增int，long，以及string类型，请参考<a href="/#/Model/CustomKey">自定义主键</a></p>
    </wt:quote>
</wt:fieldset>

<wt:fieldset field-set-style="Simple" title="BasePoco">
    <p>BasePoco是框架所有内置模型的基类，它在TopBasePoco的基础上增加了创建人，修改人，创建时间和修改时间四个字段，对于大多数模型，这些字段都是需要的</p>
    <p>建议用户自定义的模型都继承BasePoco</p>
    <wt:quote>
        <p>框架自带的添加和修改操作会自动更新创建人，修改人，创建时间和修改时间这些字段</p>
    </wt:quote>
</wt:fieldset>

<wt:fieldset field-set-style="Simple" title="PersistPoco">
    <p>PersistPoco在BasePoco的基础上增加了IsValid字段，指示框架对这类模型进行假删除</p>
    <wt:quote>
        <p>框架自带的删除功能会自动将继承PersistPoco的模型的IsValid字段设为false，而不会真正删除它</p>
    </wt:quote>
</wt:fieldset>

<wt:fieldset field-set-style="Simple" title="一对多和多对多">
    <p>模型之间的一对多和多对多的关系完全遵从EF Core默认的规则</p>
    <wt:quote>
        <p>初次使用者容易忘记定义外键名称，比如定义了一个指向School类的属性叫做ParentSchool，那么必须有一个叫做ParentSchoolId的guid属性定义外键名称，这是EF Core的默认规则</p>
        <p>如果不定义这个加Id的字段，虽然数据库可以生成，但是在代码层面是不知道外键名称的，框架的代码生成器也就无法正常工作</p>
    </wt:quote>
</wt:fieldset>

<wt:fieldset field-set-style="Simple" title="有附件的模型">
    <p>附件是系统中比较常用的，框架自带了附件表FileAttachment，需要有附件的模型只需要关联这个表就可以了</p>
    <p>比如下面例子中的Photo和PhotoId这一组属性就关联了FileAttachment表，代码生成器可以根据这个关联，自动为你生成上传文件和浏览/下载文件的功能</p>
    <wt:code title="Student.cs">
public class Student : BasePoco
{
    [Display(Name = "账号")]
    [Required(ErrorMessage = "{0}是必填项")]
    [StringLength(50, ErrorMessage = "{0}最多输入{1}个字符")]
    public string LoginName { get; set; }

    [Display(Name = "照片")]
    public Guid? PhotoId { get; set; }

    [Display(Name = "照片")]
    public FileAttachment Photo { get; set; }

}
    </wt:code>
</wt:fieldset>

<wt:fieldset field-set-style="Simple" title="其他">
    框架除了要求模型必须最终继承自TopBasePoco之外，没有其他额外要求。只要遵循EF Core的方式创建模型类就可以
</wt:fieldset>


<wt:fieldset field-set-style="Simple" title="示例">
    <wt:quote>
        <p>以下代码创建了一个学校模型，一个专业模型和一个学生模型</p>
        <p>学校和专业之间是一对多的关系，学生和专业之间是多对多的关系，通过中间表StudentMajor关联</p>
        <p>请注意这些关联关系的定义，比如School和ShoolId，Major和MajorId，Student和StudentId这些都是成对出现的</p>
        <p>StudentMajor模型上的[MiddleTable]标记，表示这是一张多对多的中间表，在中间表上加[MiddleTable]可以让代码生成器识别多对多的关系并生成正确的代码</p>
    </wt:quote>

    <wt:code title="School.cs">
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
using WalkingTec.Mvvm.Core;

namespace FirstProject.Model
{
    public enum SchoolTypeEnum {
        [Display(Name = "公立学校")]
        PUB,
        [Display(Name = "私立学校")]
        PRI
    }

    public class School : BasePoco
    {
        [Display(Name = "学校编码")]
        [Required(ErrorMessage = "{0}是必填项")]
        [RegularExpression("^[0-9]{3,3}$", ErrorMessage = "{0}必须是3位数字")]
        [StringLength(3)]
        public string SchoolCode { get; set; }

        [Display(Name = "学校名称")]
        [StringLength(50, ErrorMessage = "{0}最多输入{1}个字符")]
        [Required(ErrorMessage = "{0}是必填项")]
        public string SchoolName { get; set; }

        [Display(Name = "学校类型")]
        [Required(ErrorMessage = "{0}是必填项")]
        public SchoolTypeEnum? SchoolType { get; set; }

        [Display(Name = "备注")]
        public string Remark { get; set; }
    }

    public class Major : BasePoco
    {
        [Display(Name = "专业编码")]
        [Required(ErrorMessage = "{0}是必填项")]
        [RegularExpression("^[0-9]{3,3}$", ErrorMessage = "{0}必须是3位数字")]
        public string MajorCode { get; set; }

        [Display(Name = "专业名称")]
        [StringLength(50, ErrorMessage = "{0}最多输入{1}个字符")]
        [Required(ErrorMessage = "{0}是必填项")]
        public string MajorName { get; set; }

        [Display(Name = "备注")]
        public string Remark { get; set; }

        [Display(Name = "所属学校")]
        [Required()]
        public Guid? SchoolId { get; set; }

        [Display(Name = "所属学校")]
        public School School { get; set; }

        [Display(Name = "学生")]
        public List&ltStudentMajor&gt StudentMajors { get; set; }

    }

    public class Student : BasePoco
    {
        [Display(Name = "账号")]
        [Required(ErrorMessage = "{0}是必填项")]
        [StringLength(50, ErrorMessage = "{0}最多输入{1}个字符")]
        public string LoginName { get; set; }

        [Display(Name = "密码")]
        [Required(AllowEmptyStrings = false)]
        [StringLength(32)]
        public string Password { get; set; }

        [Display(Name = "姓名")]
        [Required(ErrorMessage = "{0}是必填项")]
        [StringLength(50, ErrorMessage = "{0}最多输入{1}个字符")]
        public string Name { get; set; }

        [Display(Name = "手机")]
        [RegularExpression("^[1][3,4,5,7,8][0-9]{9}$", ErrorMessage = "{0}格式错误")]
        public string CellPhone { get; set; }

        [Display(Name = "邮编")]
        [RegularExpression("^[0-9]{6,6}$", ErrorMessage = "{0}必须是6位数字")]
        public string ZipCode { get; set; }

        [Display(Name = "日期")]
        public DateTime? EnRollDate { get; set; }

        [Display(Name = "照片")]
        public Guid? PhotoId { get; set; }

        [Display(Name = "照片")]
        public FileAttachment Photo { get; set; }

        [Display(Name = "专业")]
        public List&ltStudentMajor&gt StudentMajor { get; set; }
    }

    [MiddleTable]
    public class StudentMajor : BasePoco
    {
        public Major Major { get; set; }
        public Student Student { get; set; }

        public Guid MajorId { get; set; }

        public Guid StudentId { get; set; }
    }
}
    </wt:code>
</wt:fieldset>

<script>
layui.use('code',function(){layui.code({ about: false })})
</script>
<script>
  $("#@Model.ViewDivId").parent().css("height", "auto");
</script>
